package top.ssrsdev.generator;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.TemplateType;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.baomidou.mybatisplus.generator.keywords.MySqlKeyWordsHandler;
import com.ssrs.framework.web.BaseController;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.HashMap;
import java.util.Map;

/**
 * 代码生成工具类
 *<p>
 *     使用了新版mybatis-plus代码生成器，没有旧版本灵活，自定义模板和文件不能指定名称路径 -_- 还不如使用旧版
 *     后面有时间直接将代码生成器做成可视化的桌面工具
 *</p>
 * @author ssrs
 */
@SuppressWarnings("ALL")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EightRoesGenerator {
    /**
     * 数据库链接
     */
    private String jdbcUrl;
    /**
     * 用户名
     */
    private String userName;
    /**
     * 密码
     */
    private String password;
    /**
     * 数据库驱动
     */
    private String driver;
    /**
     * 作者
     */
    private String author;
    /**
     * 项目路径
     */
    private String projectPath;
    /**
     * 父包路径
     */
    private String packageParent;
    /**
     * 模块名称
     */
    private String moduleName;

    /**
     * 表前缀
     */
    private String tablePrefix;


    public void generate(String... tableNamesInclude) {

        FastAutoGenerator.create(new DataSourceConfig
                .Builder(jdbcUrl, userName, password)
                .keyWordsHandler(new MySqlKeyWordsHandler())
                .typeConvert(new MySqlTypeConvert() {
                    @Override
                    public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {

                        if (fieldType.toLowerCase().contains("bit")) {
                            return DbColumnType.BOOLEAN;
                        }
                        if (fieldType.toLowerCase().contains("tinyint")) {
                            return DbColumnType.BOOLEAN;
                        }
                        if (fieldType.toLowerCase().contains("datetime")) {
                            return DbColumnType.LOCAL_DATE_TIME;
                        }
                        if (fieldType.toLowerCase().contains("date")) {
                            return DbColumnType.LOCAL_DATE;
                        }
                        if (fieldType.toLowerCase().contains("time")) {
                            return DbColumnType.LOCAL_TIME;
                        }
                        return super.processTypeConvert(globalConfig, fieldType);
                    }
                }))
                .globalConfig(builder -> {
                    builder.outputDir(projectPath + "/src/main/java")// 输出目录
                            .fileOverride() // 是否覆盖文件
                            .author(author) // 作者
                            .enableSwagger(); // 实体属性 Swagger2 注解
                })
                .packageConfig(builder -> {
                    builder.moduleName(moduleName)
                            .parent(packageParent)
                            .entity("model.entity")
                            .pathInfo(getPathInfoMap())
                            .build();
                })
                .injectionConfig(builder -> {
                    builder.beforeOutputFile((tableInfo, objectMap) -> {
                        System.out.println("tableInfo: " + tableInfo.getEntityName() + " objectMap: " + objectMap.size());
                    })
                            .customFile(getCustomFile());
                })
                .templateConfig(builder -> {
                    builder.disable(TemplateType.ENTITY)
                            .entity("/templates/entity.java")
                            .service("/templates/service.java")
                            .serviceImpl("/templates/serviceImpl.java")
                            .mapper("/templates/mapper.java")
                            .xml("/templates/mapper.xml")
                            .controller("/templates/controller.java")
                            .build();
                })
                .strategyConfig(builder -> {
                    builder.addTablePrefix(tablePrefix)
                            .addInclude(tableNamesInclude)
                            .entityBuilder()
                            .enableLombok()
                            .addTableFills(new Column("create_user", FieldFill.INSERT))
                            .addTableFills(new Column("create_time", FieldFill.INSERT))
                            .addTableFills(new Column("update_user", FieldFill.UPDATE))
                            .addTableFills(new Column("update_time", FieldFill.UPDATE))
                            .versionColumnName("version")
                            .versionPropertyName("version")
                            .logicDeleteColumnName("deleted")
                            .logicDeletePropertyName("deleteFlag")
                            .naming(NamingStrategy.underline_to_camel)
                            .columnNaming(NamingStrategy.underline_to_camel)
                            .build()
                            .controllerBuilder()
                            .superClass(BaseController.class)
                            .enableHyphenStyle()
                            .enableRestStyle()
                            .build();
                })
                .templateEngine(new VelocityTemplateEngine())
                .execute();

    }

    private Map<OutputFile, String> getPathInfoMap() {
        /**
         * 自定义文件输出路径
         */
        Map<OutputFile, String> pathInfoMap = new HashMap<>();
        pathInfoMap.put(OutputFile.xml, projectPath + "/src/main/resources/mapper/");
        pathInfoMap.put(OutputFile.other, projectPath + "/vue/");
        return pathInfoMap;
    }

    private Map<String, String> getCustomFile() {
        /**
         * 自定义文件模板 (）
         */
        Map<String, String> customFile = new HashMap();
        customFile.put("AddDTO.java", "/templates/addDTO.java.vm");
        customFile.put("EditDTO.java", "/templates/editDTO.java.vm");
        customFile.put("QueryDTO.java", "/templates/queryDTO.java.vm");
        customFile.put("api.ts", "/templates/vue/api.ts.vm");
        customFile.put("data.ts", "/templates/vue/data.ts.vm");
        customFile.put("FormModal.vue", "/templates/vue/FormModal.vue.vm");
        customFile.put("index.vue", "/templates/vue/index.vue.vm");
        return customFile;
    }

    public static void main(String[] args) {
        EightRoesGenerator eightRoesGenerator = new EightRoesGenerator().builder()
                .jdbcUrl("jdbc:mysql://101.34.215.6:3306/eight-roes-dev?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false")
                .userName("root")
                .password("ssrs_lyp82nlf")
                .driver("com.mysql.cj.jdbc.Driver")
                .author("bin.feng")
                .projectPath("D:\\tempCode")
                .packageParent("com.ssrs")
                .tablePrefix("sys_")
                .moduleName("platform").build();

        eightRoesGenerator.generate("sys_code");
    }


}
